package com.atguigu.tingshu.user.api;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.login.GuiguLogin;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.user.UserInfo;
import com.atguigu.tingshu.user.mapper.UserInfoMapper;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Tag(name = "微信授权登录接口")
@RestController
@RequestMapping("/api/user/wxLogin")
@Slf4j
public class WxLoginApiController {

    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private WxMaService wxMaService; //这里后续需要自定义配置类
    @Autowired 
    private RabbitService rabbitService;
    @Autowired
    private UserInfoMapper userInfoMapper;

    @Operation(summary = "微信小程序授权登录")
    @GetMapping("/wxLogin/{code}")
    public Result wxLogin(@PathVariable String code)throws WxErrorException {
//        1.获取每个微信得OpenID
        WxMaJscode2SessionResult sessionInfo = wxMaService.jsCode2SessionInfo(code);
        String openId = sessionInfo.getOpenid();
//        2.根据微信的OpenId查该用户的信息
        UserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getWxOpenId, openId));
//        3.如果数据库中没有用户信息，创建一个
        if (null == userInfo) {
            userInfo = new UserInfo();
//    微信小程序的自动注册，会为用户自动创建一个默认账号，你把它set进去
            userInfo.setWxOpenId(openId);
            userInfo.setNickname("听友" + System.currentTimeMillis());
            userInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
            userInfo.setWxOpenId(openId);
            userInfoMapper.insert(userInfo);
//            初始化账户信息(用消息队列触发新用户账户初始化的后续操作)
            rabbitService.sendMessage(MqConst.EXCHANGE_USER, MqConst.ROUTING_USER_REGISTER, userInfo.getId());
        }
            //            创建token
            String token = UUID.randomUUID().toString().replaceAll("-","");
//            将这两个数据(token和用户信息)存储到缓存中：
           String userLoginKey = RedisConstant.USER_LOGIN_KEY_PREFIX+token;
           redisTemplate.opsForValue().set(userLoginKey,userInfo,RedisConstant.USER_LOGIN_KEY_TIMEOUT,TimeUnit.SECONDS);
//            将这个数据存储到map中并返回：
            HashMap<String,Object> map = new HashMap<>();
            map.put("token",token);

            //            返回数据：
            return Result.ok(map);
        }


    @GuiguLogin
    @Operation(summary = "获取用户登录信息")
    @GetMapping("/getUserInfo")
    public Result getUserInfo(){
//  思路：从请求头中获取token，利用token生成key。从缓存获取数据放进线程，这样才能用AuthContextHolder中获取用户id
//    1.从当前线程中获取用户id
        Long userId = AuthContextHolder.getUserId();
//    2.调用服务层方法,根据userid获取用户信息Vo
        UserInfoVo userInfoVo = userInfoService.getUserInfoVoByUserId(userId);
//    3.返回数据
        return Result.ok(userInfoVo);
    }


    /**
     * 更新用户信息
     * @param userInfoVo
     * @return
     */
    @GuiguLogin
    @Operation(summary = "更新用户信息")
    @PostMapping("/updateUser")
    public Result updateUser(@RequestBody UserInfoVo userInfoVo){
//        1.从线程中获取用户id
        Long userId = AuthContextHolder.getUserId();
//        2.调用服务层更新方法
        userInfoService.updateUser(userId,userInfoVo);
//        4.返回ok
        return Result.ok();
    }




}